// 10__SMSTasker.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "CFactory.h"

extern int g_cServerLocks;

//#define INITGUID
// {52AF0A66-6707-4a64-A1AF-DFFD973D2B14}
DEFINE_GUID(CLSID_SMSTasker, 0x52af0a66, 0x6707, 0x4a64, 0xa1, 0xaf, 0xdf, 0xfd, 0x97, 0x3d, 0x2b, 0x14);

//TODO
/* Add to apps.reg:
[HKEY_CLASSES_ROOT\CLSID\{52AF0A66-6707-4a64-A1AF-DFFD973D2B14}\InProcServer32]
@="smstasker.dll"
*/

//TODO
/*
Add this line too:
[HKEY_LOCAL_MACHINE\Software\Microsoft\Inbox\Svc\SMS\Rules]
"{52AF0A66-6707-4a64-A1AF-DFFD973D2B14}"=dword:1
*/

HMODULE hInst = NULL;

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
	hInst = (HMODULE)hModule;
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		DisableThreadLibraryCalls((HMODULE)hModule);
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		hInst = NULL;
		SHNotificationRemove(&CLSID_SMSTasker, 1);
		break;
	}
    return TRUE;
}

// **************************************************************************
// Function Name: DllGetClassObject
// Purpose: Retrieves the class object from the DLL object

// Arguments: IN CLSID& clsid - CLSID for desired class object
//			  IN REFIID iid - ref to interface id, usually IClassFactory
//			  OUT LPVOID *ppv - address of requested interface pointer

// Return Values: HRESULT

// Side effects:  

// Description:  
STDAPI DllGetClassObject(const CLSID& clsid, REFIID iid, LPVOID *ppv)
{
	HRESULT hr;

	// We only understand this rule's class
	if (clsid != CLSID_SMSTasker)
	{
		return CLASS_E_CLASSNOTAVAILABLE;
	}

	CFactory *pFactory = new CFactory;
	if (!pFactory)
	{
		return E_OUTOFMEMORY;
	}

	// Get the requested interface
	hr = pFactory->QueryInterface(iid, ppv);
	pFactory->Release();

	return hr;
}

// **************************************************************************
// Function Name: DllCanUnloadNow
//
// Purpose: Notify caller if dll can safely be unloaded

// Arguments: none

// Return Values: HRESULT, S_OK if safe to unload, S_FALSE otherwise

// Side effects:  

// Description:  A call to DllCanUnloadNow determines whether the DLL from 
//	which it is exported is still in use. A DLL is no longer in use when it 
//	is not managing any existing objects (the reference count on all of its 
//	objects is zero). 

STDAPI DllCanUnloadNow()
{
	if (!g_cServerLocks)
	{

		return S_OK;
	}
	else
	{
		return S_FALSE;
	}
}

// **************************************************************************
// Function Name: DllRegisterServer
//
// Purpose: provide DLL with the ability to register its COM objects

// Arguments: none

// Return Values: HRESULT - S_OK if registration succeeds, E_FAIL otherwise

// Side effects: In order to fully remove the plugin, both registry keys should
//	be removed (see Description below). DllUnregisterServer does this.

// Description:  
//  In addition to standard COM object registration, the function also must
//  register our rule client handler with Inbox.  We are registering our 
//	DLL in two places, HKEY_CLASSES_ROOT\CLSID\, and HKEY_LOCAL_MACHINE\Software
//	\Microsoft\Inbox\Svc\SMS\Rules
STDAPI DllRegisterServer()
{
	LRESULT lr;
	HRESULT hr = E_FAIL;
	HKEY hKey = NULL;
	HKEY hSubKey = NULL;
	DWORD dwDisposition;
	TCHAR wszValue[20];

	// Set up registry keys
	// Register with COM:
	//    [HKEY_CLASSES_ROOT\CLSID\{3AB4C10E-673C-494c-98A2-CC2E91A48115}\InProcServer32]
	//    @="mapirule.dll"


	lr = RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("\\CLSID\\{52AF0A66-6707-4a64-A1AF-DFFD973D2B14}"),
		0, NULL, 0, 0, NULL, 
		&hKey, &dwDisposition);
	if (lr != ERROR_SUCCESS)
	{
		goto Exit;
	}

	lr = RegCreateKeyEx(hKey, TEXT("InprocServer32"),
		0, NULL, 0, 0, NULL, 
		&hSubKey, &dwDisposition);
	if (lr != ERROR_SUCCESS)
	{
		goto Exit;
	}

	lstrcpy(wszValue, TEXT("smstasker.dll"));
	lr = RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (LPBYTE) wszValue, (lstrlen(wszValue) + 1) * sizeof(TCHAR));
	if (lr != ERROR_SUCCESS)
	{
		goto Exit;
	}

	RegCloseKey(hSubKey);
	hSubKey = NULL;
	RegCloseKey(hKey);
	hKey = NULL;

	// Register with Inbox:
	//    [HKEY_LOCAL_MACHINE\Software\Microsoft\Inbox\Svc\SMS\Rules]
	//    {3AB4C10E-673C-494c-98A2-CC2E91A48115}"=dword:1

	lr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("\\Software\\Microsoft\\Inbox\\Svc\\SMS\\Rules"),
		0, NULL, 0, 0, NULL, 
		&hKey, &dwDisposition);
	if (lr != ERROR_SUCCESS)
	{
		goto Exit;
	}

	dwDisposition = 1;
	lr = RegSetValueEx(hKey, TEXT("{52AF0A66-6707-4a64-A1AF-DFFD973D2B14}"), 0, REG_DWORD, 
		(LPBYTE) &dwDisposition, sizeof(DWORD));
	if (lr != ERROR_SUCCESS)
	{
		goto Exit;
	}

	hr = S_OK;

Exit:
	if (hSubKey)
	{
		RegCloseKey(hSubKey);
	}
	if (hKey)
	{
		RegCloseKey(hKey);
	}

	return hr;
}

// **************************************************************************
// Function Name: DllUnregisterServer
// Purpose: rovide DLL with the ability to un-register its COM objects
// Arguments: none
// Return Values: HRESULT - S_OK if registration succeeds, E_FAIL otherwise
// Side effects: 
// Description:  Deletes both the COM registry key and the key used to register
// the rule client with Inbox
STDAPI DllUnregisterServer()
{
	HKEY hKey = NULL;
	HRESULT hr = E_FAIL;
	LRESULT lr;
	DWORD dwDisposition;

	// Delete registry keys
	RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("\\CLSID\\{52AF0A66-6707-4a64-A1AF-DFFD973D2B14}"));

	lr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("\\Software\\Microsoft\\Inbox\\Svc\\SMS\\Rules"),
		0, NULL, 0, 0, NULL, 
		&hKey, &dwDisposition);
	if (lr != ERROR_SUCCESS)
	{
		goto Exit;
	}

	RegDeleteValue(hKey, TEXT("{52AF0A66-6707-4a64-A1AF-DFFD973D2B14}"));

	hr = S_OK;

Exit:
	if (hKey)
	{
		RegCloseKey(hKey);
	}

	return hr;
}